﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Projet_IMA.Unsafe;
using Projet_IMA.Environnement;
using Projet_IMA.Base;

namespace Projet_IMA.Projections
{
    public class ProjectionPerspective : ProjectionBase
    {
        /*
        public UnsafePoint3D CameraPosition = new UnsafePoint3D();
        public UnsafePoint3D CameraOrientation = new UnsafePoint3D();
        public UnsafePoint3D CameraOrientationSinusValue = new UnsafePoint3D();
        public UnsafePoint3D CameraOrientationCosinusValue = new UnsafePoint3D();
          */

        public V3 c;
        public V3 O;
        public V3 e;
        public V3 SinO;
        public V3 CosO;

        public ProjectionPerspective()
        {
            this.c = new V3(-100, -100, -200);
            this.e = new V3(0, 0, 1000);
            this.O = new V3(-0.3F, 0.6F,0.3F);

            this.SinO = new V3(MF.Sin(this.O.x), MF.Sin(this.O.y), MF.Sin(this.O.z));
            this.CosO = new V3(MF.Cos(this.O.x), MF.Cos(this.O.y), MF.Cos(this.O.z));
        }

        public override String Name
        {
            get { return "Perspective"; }
        }

        public override EProjection EProjection
        {
            get { return EProjection.Perspective; }
        }

        public override EProjectionType EProjectionType
        {
            get { return EProjectionType.Perspective; }
        }

        public override unsafe void GetProjection(UnsafePoint3D* Point, UnsafePoint2D* projectionPoint)
        {            
            // http://en.wikipedia.org/wiki/3D_projection
            projectionPoint->x = 0 + (int)(CosO.y * (SinO.z * (-Point->z - c.y) + CosO.z * (Point->x - c.x)) - SinO.y * (Point->y - c.z));
            projectionPoint->y = 0 + (int)(SinO.x * (CosO.y * (Point->y - c.z) + SinO.y * (SinO.z * (-Point->z - c.y) + CosO.z * (Point->x - c.x))) + CosO.x * (CosO.z * (-Point->z - c.y) - SinO.z * (Point->x - c.x)));
            projectionPoint->profondeur = (int)(CosO.x * (CosO.y * (Point->y - c.z) + SinO.y * (SinO.z * (-Point->z - c.y) + CosO.z * (Point->x - c.x))) - SinO.x * (CosO.z * (-Point->z - c.y) - SinO.z * (Point->x - c.x)));

            
            double Zprojection;
            if (projectionPoint->profondeur == 0)
            {
                Zprojection = 0;
            }
            else
            {
                Zprojection = (e.z / (projectionPoint->profondeur + e.z));
            }

            projectionPoint->x = ZeroX + (int)(projectionPoint->x * Zprojection);
            projectionPoint->y = ZeroY + (int)(projectionPoint->y * Zprojection);
        }

        public override void setCameraDirection(V3 cameraDirection)
        {
            cameraDirection.x = c.x;
            cameraDirection.y = c.y;
            cameraDirection.z = c.z;
        }
    }
}
